package com.joe.bibackend.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import com.joe.bibackend.bean.ChartBean;
import com.joe.bibackend.bean.UserBean;
import com.joe.bibackend.bean.dto.ChartResponseDTO;
import com.joe.bibackend.bean.vo.UploadFileRequestVO;
import com.joe.bibackend.e.ResponseCode;
import com.joe.bibackend.manager.RedisLimiterManager;
import com.joe.bibackend.response.NormalResponse;
import com.joe.bibackend.service.ChartBeanService;
import com.joe.bibackend.service.ChartService;
import org.redisson.RedissonRateLimiter;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

@RequestMapping("/chart")
@RestController
public class ChartController {

    private final long TWO_MB = 1024*1024L*2;

    @Resource
    private ChartService chartService;

    @Resource
    private ChartBeanService chartBeanService;

    @Resource
    private RedisLimiterManager redisLimiterManager;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    final List<String> validFileSuffixList = Arrays.asList("xml","xlsx","xls");

    @PostMapping("/upload")
    public NormalResponse<ChartResponseDTO> uploadExcelReading(@RequestPart("file")MultipartFile file,
                                                               UploadFileRequestVO requestVO, HttpServletRequest request){

        long fileSize = file.getSize();
        if(fileSize > TWO_MB){
            return new NormalResponse<>(null,ResponseCode.FAILED_INFO);
        }
        String fileSuffix = FileUtil.getSuffix(file.getOriginalFilename());
        if(!validFileSuffixList.contains(fileSuffix)){
            return new NormalResponse<>(null,ResponseCode.FAILED_INFO);
        }
        UserBean userBean = new UserBean();
        Object result = request.getSession().getAttribute("userState");
        if(result != null){
            userBean = (UserBean) request;
        }else {
            return new NormalResponse<>(null,ResponseCode.FAILED);
        }
        redisLimiterManager.doRateLimit("RedisLimit:"+userBean.getCreateTime());
        ChartBean chartBean = new ChartBean();
        String chartName = requestVO.getChartName();
        String chartType = requestVO.getChartType();
        String goal = requestVO.getGoal();
        chartBean.setChartName(chartName);
        chartBean.setChartType(chartType);
        chartBean.setGoal(goal);
        chartBeanService.save(chartBean);
        chartBean.setStatus("wait");
        ChartResponseDTO responseDTO = new ChartResponseDTO();
        CompletableFuture.runAsync(() -> {
            ChartBean updateBean = new ChartBean();
            updateBean.setId(chartBean.getId());
            updateBean.setStatus("running");
            boolean b = chartBeanService.updateById(chartBean);
            if(!b){
                throw new RuntimeException("Something wrong with the database");
            }
            responseDTO.setReturnedInfo(chartService.getChartResponseFromAI(chartType,goal,file));
            ChartBean updateChartResult = new ChartBean();
            updateChartResult.setId(chartBean.getId());
            updateChartResult.setChartData(responseDTO.getReturnedInfo().get("echart"));
            updateChartResult.setGenChart(responseDTO.getReturnedInfo().get("analysis"));
            updateChartResult.setStatus("success");
            boolean updateResult = chartBeanService.updateById(updateChartResult);
            if(!updateResult){
                throw new RuntimeException("incidence happens during AI generation");
            }
        },threadPoolExecutor);


        if(CollectionUtil.isEmpty(responseDTO.getReturnedInfo())){
            return new NormalResponse<>(null,ResponseCode.FAILED_INFO);
        }


        return new NormalResponse<>(responseDTO,ResponseCode.SUCCESS_LOGIN);
    }
}
